home *** CD-ROM | disk | FTP | other *** search
/ Almathera Ten Pack 2: CDPD 1 / Almathera Ten on Ten - Disc 2: CDPD 1.iso / pd / 351-375 / 351 / pdc / pdcsrc.lzh / PDC / Optimize.c < prev    next >
C/C++ Source or Header  |  1990-04-06  |  21KB  |  844 lines

  1.  
  2. /* PDC Compiler - A Freely Distributable C Compiler for the Amiga
  3.  *                Based upon prior work by Matthew Brandt and Jeff Lydiatt.
  4.  *
  5.  * PDC Compiler release 3.3 Copyright (C) 1989 Paul Petersen and Lionel Hummel.
  6.  * PDC Software Distribution (C) 1989 Lionel Hummel and Paul Petersen.
  7.  *
  8.  * This code is freely redistributable upon the conditions that this 
  9.  * notice remains intact and that modified versions of this file not be 
  10.  * distributed as part of the PDC Software Distribution without the express
  11.  * consent of the copyright holders.
  12.  *
  13.  *------------------------------------------------------------------
  14.  *
  15.  * $Log:    Optimize.c,v $
  16.  * Revision 3.33  90/04/05  22:42:41  lionel
  17.  * Added cases for unsigned *, /, %, *=, /=, and %= expressions.
  18.  * 
  19.  * Revision 3.32  90/02/03  16:24:59  lionel
  20.  * None
  21.  * 
  22.  *------------------------------------------------------------------
  23.  */
  24.  
  25. /*
  26.  * Optimize.c
  27.  * 
  28.  * Applies the various optimizations known by PDC.
  29.  */
  30.  
  31. #include        <stdio.h>
  32. #include        "C.h"
  33. #include        "Expr.h"
  34. #include        "Gen.h"
  35. #include        "Cglbdec.h"
  36.  
  37. extern struct enode *makenode();
  38. extern void    *remlit();
  39. extern void    *getlit();
  40. extern long     floatlit();
  41.  
  42. void            fold_const();
  43.  
  44. int
  45. fetchdouble(node, result)
  46.     struct enode   *node;
  47.     double         *result;
  48. {
  49.     double         *ptr;
  50.  
  51.     if (result == NULL)
  52.         return (0);
  53.  
  54.     *result = 0.0;
  55.  
  56.     if (node->nodetype == en_d_ref) {
  57.         if (node->v.p[0]->nodetype == en_labcon) {
  58.             if ((ptr = (double *) getlit(node->v.p[0]->v.i)) != NULL) {
  59.                 *result = *ptr;
  60.                 return (1);
  61.             }
  62.         }
  63.     }
  64.     return (0);
  65. }
  66.  
  67. void
  68. dooper(node)
  69.  
  70. /*
  71.  * dooper will execute a constant operation in a node and modify the node to
  72.  * be the result of the operation.
  73.  */
  74.     struct enode  **node;
  75. {
  76.     struct enode   *ep;
  77.     double          rval;
  78.  
  79.     ep = *node;
  80.     switch (ep->nodetype) {
  81.     case en_uminus:
  82.         ep->nodetype = en_icon;
  83.         ep->v.i = -ep->v.p[0]->v.i;
  84.         break;
  85.     case en_not:
  86.         ep->nodetype = en_icon;
  87.         ep->v.i = !ep->v.p[0]->v.i;
  88.         break;
  89.     case en_compl:
  90.         ep->nodetype = en_icon;
  91.         ep->v.i = ~ep->v.p[0]->v.i;
  92.         break;
  93.     case en_add:
  94.         ep->nodetype = en_icon;
  95.         ep->v.i = ep->v.p[0]->v.i + ep->v.p[1]->v.i;
  96.         break;
  97.     case en_sub:
  98.         ep->nodetype = en_icon;
  99.         ep->v.i = ep->v.p[0]->v.i - ep->v.p[1]->v.i;
  100.         break;
  101.     case en_mul:
  102.         ep->nodetype = en_icon;
  103.         ep->v.i = ep->v.p[0]->v.i * ep->v.p[1]->v.i;
  104.         break;
  105.     case en_div:
  106.         ep->nodetype = en_icon;
  107.         ep->v.i = ep->v.p[0]->v.i / ep->v.p[1]->v.i;
  108.         break;
  109.     case en_lsh:
  110.         ep->nodetype = en_icon;
  111.         ep->v.i = ep->v.p[0]->v.i << ep->v.p[1]->v.i;
  112.         break;
  113.     case en_rsh:
  114.         ep->nodetype = en_icon;
  115.         ep->v.i = ep->v.p[0]->v.i >> ep->v.p[1]->v.i;
  116.         break;
  117.     case en_and:
  118.         ep->nodetype = en_icon;
  119.         ep->v.i = ep->v.p[0]->v.i & ep->v.p[1]->v.i;
  120.         break;
  121.     case en_or:
  122.         ep->nodetype = en_icon;
  123.         ep->v.i = ep->v.p[0]->v.i | ep->v.p[1]->v.i;
  124.         break;
  125.     case en_xor:
  126.         ep->nodetype = en_icon;
  127.         ep->v.i = ep->v.p[0]->v.i ^ ep->v.p[1]->v.i;
  128.         break;
  129.     case en_land:
  130.         ep->nodetype = en_icon;
  131.         ep->v.i = ep->v.p[0]->v.i && ep->v.p[1]->v.i;
  132.         break;
  133.     case en_lor:
  134.         ep->nodetype = en_icon;
  135.         ep->v.i = ep->v.p[0]->v.i || ep->v.p[1]->v.i;
  136.         break;
  137.     case en_lt:
  138.     case en_ult:
  139.         ep->nodetype = en_icon;
  140.         ep->v.i = ep->v.p[0]->v.i < ep->v.p[1]->v.i;
  141.         break;
  142.     case en_le:
  143.     case en_ule:
  144.         ep->nodetype = en_icon;
  145.         ep->v.i = ep->v.p[0]->v.i <= ep->v.p[1]->v.i;
  146.         break;
  147.     case en_gt:
  148.     case en_ugt:
  149.         ep->nodetype = en_icon;
  150.         ep->v.i = ep->v.p[0]->v.i > ep->v.p[1]->v.i;
  151.         break;
  152.     case en_ge:
  153.     case en_uge:
  154.         ep->nodetype = en_icon;
  155.         ep->v.i = ep->v.p[0]->v.i >= ep->v.p[1]->v.i;
  156.         break;
  157.     case en_eq:
  158.         ep->nodetype = en_icon;
  159.         ep->v.i = ep->v.p[0]->v.i == ep->v.p[1]->v.i;
  160.         break;
  161.     case en_ne:
  162.         ep->nodetype = en_icon;
  163.         ep->v.i = ep->v.p[0]->v.i != ep->v.p[1]->v.i;
  164.         break;
  165.     case en_cdl:
  166.     case en_cfl:
  167.         ep->nodetype = en_icon;
  168.         ep->v.i = ep->v.p[0]->v.f;
  169.         break;
  170.     case en_cld:
  171.         rval = ep->v.p[0]->v.i;
  172.         ep = makenode(en_labcon, floatlit(rval), NULL);
  173.         *node = makenode(en_d_ref, ep, NULL);
  174.         break;
  175.     case en_fnegd:
  176.         rval = -(ep->v.p[0]->v.f);
  177.         ep = makenode(en_labcon, floatlit(rval), NULL);
  178.         *node = makenode(en_d_ref, ep, NULL);
  179.         break;
  180.     case en_faddd:
  181.         rval = ep->v.p[0]->v.f + ep->v.p[1]->v.f;
  182.         ep = makenode(en_labcon, floatlit(rval), NULL);
  183.         *node = makenode(en_d_ref, ep, NULL);
  184.         break;
  185.     case en_fsubd:
  186.         rval = ep->v.p[0]->v.f - ep->v.p[1]->v.f;
  187.         ep = makenode(en_labcon, floatlit(rval), NULL);
  188.         *node = makenode(en_d_ref, ep, NULL);
  189.         break;
  190.     case en_fmuld:
  191.         rval = ep->v.p[0]->v.f * ep->v.p[1]->v.f;
  192.         ep = makenode(en_labcon, floatlit(rval), NULL);
  193.         *node = makenode(en_d_ref, ep, NULL);
  194.         break;
  195.     case en_fdivd:
  196.         rval = ep->v.p[0]->v.f / ep->v.p[1]->v.f;
  197.         ep = makenode(en_labcon, floatlit(rval), NULL);
  198.         *node = makenode(en_d_ref, ep, NULL);
  199.         break;
  200.     }
  201. }
  202.  
  203. int
  204. pwrof2(i)
  205.  
  206. /*
  207.  * return which power of two i is or -1.
  208.  */
  209.     int             i;
  210. {
  211.     int             p, q;
  212.  
  213.     q = 2;
  214.     p = 1;
  215.     while (q > 0) {
  216.         if (q == i)
  217.             return p;
  218.         q <<= 1;
  219.         ++p;
  220.     }
  221.     return -1;
  222. }
  223.  
  224. int
  225. mod_mask(i)
  226.  
  227. /*
  228.  * make a mod mask for a power of two.
  229.  */
  230.     int             i;
  231. {
  232.     int             m;
  233.  
  234.     m = 0;
  235.     while (i--)
  236.         m = (m << 1) | 1;
  237.     return m;
  238. }
  239.  
  240. void
  241. ref_double(node)
  242.     struct enode   *node;
  243. {
  244.     struct enode   *ep;
  245.     double         *dptr;
  246.  
  247.     ep = node->v.p[0];
  248.     if (ep->nodetype != en_fcon) {
  249.         if (ep->nodetype != en_d_ref)
  250.             return;
  251.         if (ep->v.p[0]->nodetype != en_labcon)
  252.             return;
  253.         if (getlit(ep->v.p[0]->v.i) == NULL) 
  254.             return;
  255.     }
  256.  
  257.     ep = node->v.p[0];
  258.     if (ep->nodetype != en_fcon) {
  259.         dptr = (double *) remlit(ep->v.p[0]->v.i);
  260.         ep->v.f = *dptr;
  261.         ep->nodetype = en_fcon;
  262.     }
  263. }
  264.  
  265.  
  266. void
  267. ref2_double(node)
  268.     struct enode   *node;
  269. {
  270.     int             i;
  271.     struct enode   *ep;
  272.     double         *dptr;
  273.  
  274.     for (i = 0; i < 2; i++) {
  275.         ep = node->v.p[i];
  276.         if (ep->nodetype != en_fcon) {
  277.             if (ep->nodetype != en_d_ref)
  278.                 return;
  279.             if (ep->v.p[0]->nodetype != en_labcon)
  280.                 return;
  281.             if (getlit(ep->v.p[0]->v.i) == NULL) 
  282.                 return;
  283.         }
  284.     }
  285.  
  286.     for (i = 0; i < 2; i++) {
  287.         ep = node->v.p[i];
  288.         if (ep->nodetype != en_fcon) {
  289.             if ((dptr = (double *) remlit(ep->v.p[0]->v.i)) != NULL) {
  290.                 ep->v.f = *dptr;
  291.                 ep->nodetype = en_fcon;
  292.             }
  293.         }
  294.     }
  295. }
  296.  
  297. void
  298. opt0(node)
  299.  
  300. /*
  301.  * opt0 - delete useless expressions and combine constants.
  302.  * 
  303.  * opt0 will delete expressions such as x + 0, x - 0, x * 0, x * 1, 0 / x, x /
  304.  * 1, x mod 0, etc from the tree pointed to by node and combine obvious
  305.  * constant operations. It cannot combine name and label constants but will
  306.  * combine icon type nodes.
  307.  */
  308.     struct enode  **node;
  309. {
  310.     struct enode   *ep;
  311.     int             sc;
  312.     long            val;
  313.     double          dval;
  314.  
  315.     ep = *node;
  316.  
  317.     if (ep == NULL)
  318.         return;
  319.  
  320.     switch ((*node)->nodetype) {
  321.     case en_b_ref:
  322.     case en_ub_ref:
  323.     case en_w_ref:      /* optimize unary node */
  324.     case en_uw_ref:
  325.     case en_l_ref:
  326.     case en_m_ref:
  327.     case en_d_ref:
  328.     case en_f_ref:
  329.     case en_cbw:
  330.     case en_cbl:
  331.     case en_cwl:
  332.     case en_cfd:
  333.     case en_cdf:
  334.  
  335.     case en_info:
  336.         opt0(&((*node)->v.p[0]));
  337.         return;
  338.         break;
  339.  
  340.     case en_ainc:
  341.     case en_adec:
  342.     case en_faincs:
  343.     case en_fadecs:
  344.     case en_faincd:
  345.     case en_fadecd:
  346.         opt0(&((*node)->v.p[0]));
  347.         opt0(&((*node)->v.p[1]));
  348.         return;
  349.  
  350.     case en_not:
  351.     case en_compl:
  352.     case en_uminus:
  353.         opt0(&(ep->v.p[0]));
  354.         if (ep->v.p[0]->nodetype == en_icon)
  355.             dooper(node);
  356.         return;
  357.     case en_add:
  358.     case en_sub:
  359.         opt0(&(ep->v.p[0]));
  360.         opt0(&(ep->v.p[1]));
  361.         if (ep->v.p[0]->nodetype == en_icon) {
  362.             if (ep->v.p[1]->nodetype == en_icon) {
  363.                 dooper(node);
  364.                 return;
  365.             }
  366.             if (ep->v.p[0]->v.i == 0) {
  367.                 if (ep->nodetype == en_sub) {
  368.                     ep->v.p[0] = ep->v.p[1];
  369.                     ep->nodetype = en_uminus;
  370.                 }
  371.                 else
  372.                     *node = ep->v.p[1];
  373.                 return;
  374.             }
  375.         }
  376.         else if (ep->v.p[1]->nodetype == en_icon) {
  377.             if (ep->v.p[1]->v.i == 0) {
  378.                 *node = ep->v.p[0];
  379.                 return;
  380.             }
  381.         }
  382.         return;
  383.     case en_mul:
  384.         opt0(&(ep->v.p[0]));
  385.         opt0(&(ep->v.p[1]));
  386.         if (ep->v.p[0]->nodetype == en_icon) {
  387.             if (ep->v.p[1]->nodetype == en_icon) {
  388.                 dooper(node);
  389.                 return;
  390.             }
  391.             val = ep->v.p[0]->v.i;
  392.             if (val == 0) {
  393.                 *node = ep->v.p[0];
  394.                 return;
  395.             }
  396.             if (val == 1) {
  397.                 *node = ep->v.p[1];
  398.                 return;
  399.             }
  400.             sc = pwrof2((int) val);
  401.             if (sc != -1) {
  402.                 swap_nodes(ep);
  403.                 ep->v.p[1]->v.i = sc;
  404.                 ep->nodetype = en_lsh;
  405.             }
  406.         }
  407.         else if (ep->v.p[1]->nodetype == en_icon) {
  408.             val = ep->v.p[1]->v.i;
  409.             if (val == 0) {
  410.                 *node = ep->v.p[1];
  411.                 return;
  412.             }
  413.             if (val == 1) {
  414.                 *node = ep->v.p[0];
  415.                 return;
  416.             }
  417.             sc = pwrof2((int) val);
  418.             if (sc != -1) {
  419.                 ep->v.p[1]->v.i = sc;
  420.                 ep->nodetype = en_lsh;
  421.             }
  422.         }
  423.         break;
  424.     case en_div:
  425.         opt0(&(ep->v.p[0]));
  426.         opt0(&(ep->v.p[1]));
  427.         if (ep->v.p[0]->nodetype == en_icon) {
  428.             if (ep->v.p[1]->nodetype == en_icon) {
  429.                 dooper(node);
  430.                 return;
  431.             }
  432.             if (ep->v.p[0]->v.i == 0) { /* 0/x */
  433.                 *node = ep->v.p[0];
  434.                 return;
  435.             }
  436.         }
  437.         else if (ep->v.p[1]->nodetype == en_icon) {
  438.             val = ep->v.p[1]->v.i;
  439.             if (val == 1) { /* x/1 */
  440.                 *node = ep->v.p[0];
  441.                 return;
  442.             }
  443.             if (! Options.MulDiv32) {
  444.                 sc = pwrof2((int) val);
  445.                 if (sc != -1) {
  446.                     ep->v.p[1]->v.i = sc;
  447.                     ep->nodetype = en_rsh;
  448.                 }
  449.             }
  450.         }
  451.         break;
  452.     case en_mod:
  453.     case en_umod:
  454.         opt0(&(ep->v.p[0]));
  455.         opt0(&(ep->v.p[1]));
  456.         if (ep->v.p[1]->nodetype == en_icon) {
  457.             if (ep->v.p[0]->nodetype == en_icon) {
  458.                 dooper(node);
  459.                 return;
  460.             }
  461.             if (! Options.MulDiv32) {
  462.                 sc = pwrof2((int) (ep->v.p[1]->v.i));
  463.                 if (sc != -1) {
  464.                     ep->v.p[1]->v.i = mod_mask(sc);
  465.                     ep->nodetype = en_and;
  466.                 }
  467.             }
  468.         }
  469.         break;
  470.     case en_and:
  471.     case en_or:
  472.     case en_xor:
  473.     case en_rsh:
  474.     case en_lsh:
  475.     case en_lt:
  476.     case en_le:
  477.     case en_gt:
  478.     case en_ge:
  479.     case en_eq:
  480.     case en_ne:
  481.     case en_land:
  482.     case en_lor:
  483.         opt0(&(ep->v.p[0]));
  484.         opt0(&(ep->v.p[1]));
  485.         if (ep->v.p[0]->nodetype == en_icon &&
  486.             ep->v.p[1]->nodetype == en_icon)
  487.             dooper(node);
  488.         break;
  489.     case en_asand:
  490.     case en_asor:
  491.     case en_asadd:
  492.     case en_assub:
  493.         opt0(&(ep->v.p[0]));
  494.         opt0(&(ep->v.p[1]));
  495.         break;
  496.     case en_asmul:
  497.     case en_asumul:
  498.         opt0(&(ep->v.p[0]));
  499.         opt0(&(ep->v.p[1]));
  500.         if (ep->v.p[1]->nodetype == en_icon) {
  501.             val = ep->v.p[1]->v.i;
  502.             if (val == 0) {
  503.                 (*node)->nodetype = en_assign;
  504.                 return;
  505.             }
  506.             if (val == 1) {
  507.                 *node = ep->v.p[0];
  508.                 return;
  509.             }
  510.             sc = pwrof2((int) val);
  511.             if (sc != -1) {
  512.                 ep->v.p[1]->v.i = sc;
  513.                 ep->nodetype = en_aslsh;
  514.             }
  515.         }
  516.         break;
  517.     case en_asdiv:
  518.     case en_asudiv:
  519.         opt0(&(ep->v.p[0]));
  520.         opt0(&(ep->v.p[1]));
  521.         if (ep->v.p[1]->nodetype == en_icon) {
  522.             val = ep->v.p[1]->v.i;
  523.             if (val == 1) {
  524.                 *node = ep->v.p[0];
  525.                 return;
  526.             }
  527.             if (! Options.MulDiv32) {
  528.                 sc = pwrof2((int) val);
  529.                 if (sc != -1) {
  530.                     ep->v.p[1]->v.i = sc;
  531.                     ep->nodetype = en_asrsh;
  532.                 }
  533.             }
  534.         }
  535.         break;
  536.     case en_asmod:
  537.     case en_asumod:
  538.         opt0(&(ep->v.p[0]));
  539.         opt0(&(ep->v.p[1]));
  540.         if (ep->v.p[1]->nodetype == en_icon) {
  541.             if (! Options.MulDiv32) {
  542.                 val = ep->v.p[1]->v.i;
  543.                 sc = pwrof2((int) val);
  544.                 if (sc != -1) {
  545.                     ep->v.p[1]->v.i = mod_mask(sc);
  546.                     ep->nodetype = en_asand;
  547.                 }
  548.             }
  549.         }
  550.         break;
  551.     case en_cond:
  552.         opt0(&(ep->v.p[0]));
  553.         opt0(&(ep->v.p[1]->v.p[0]));
  554.         opt0(&(ep->v.p[1]->v.p[1]));
  555.         if (ep->v.p[0]->nodetype == en_icon) {
  556.             if (ep->v.p[0]->v.i) 
  557.                 *node = ep->v.p[1]->v.p[0];
  558.             else
  559.                 *node = ep->v.p[1]->v.p[1];
  560.         }
  561.         break;
  562.     case en_asrsh:
  563.     case en_aslsh:
  564.     case en_fcall:
  565.     case en_void:
  566.     case en_assign:
  567.         opt0(&(ep->v.p[0]));
  568.         opt0(&(ep->v.p[1]));
  569.         break;
  570.     case en_fnegd:
  571.     case en_fnegs:
  572.         opt0(&(ep->v.p[0]));
  573.         ref_double(ep);
  574.         if (ep->v.p[0]->nodetype == en_fcon)
  575.             dooper(node);
  576.         break;
  577.     case en_faddd:
  578.         opt0(&(ep->v.p[0]));
  579.         opt0(&(ep->v.p[1]));
  580.         if (fetchdouble(ep->v.p[0], &dval)) {
  581.             if (dval == 0.0) {  /* 0.0 + X */
  582.                 *node = ep->v.p[1];
  583.                 (void) remlit(ep->v.p[0]->v.p[0]->v.i);
  584.                 return;
  585.             }
  586.         }
  587.         if (fetchdouble(ep->v.p[1], &dval)) {
  588.             if (dval == 0.0) {  /* X + 0.0 */
  589.                 *node = ep->v.p[0];
  590.                 (void) remlit(ep->v.p[1]->v.p[0]->v.i);
  591.                 return;
  592.             }
  593.         }
  594.         ref2_double(ep);
  595.         if (ep->v.p[0]->nodetype == en_fcon && ep->v.p[1]->nodetype == en_fcon)
  596.             dooper(node);
  597.         break;
  598.     case en_fsubd:
  599.         opt0(&(ep->v.p[0]));
  600.         opt0(&(ep->v.p[1]));
  601.         if (fetchdouble(ep->v.p[0], &dval)) {
  602.             if (dval == 0.0) {  /* 0.0 - X */
  603.                 (void) remlit(ep->v.p[0]->v.p[0]->v.i);
  604.                 (*node)->v.p[0] = (*node)->v.p[1];
  605.                 (*node)->v.p[1] = NULL;
  606.                 (*node)->nodetype = en_fnegd;
  607.                 return;
  608.             }
  609.         }
  610.         if (fetchdouble(ep->v.p[1], &dval)) {
  611.             if (dval == 0.0) {  /* X - 0.0 */
  612.                 *node = ep->v.p[0];
  613.                 (void) remlit(ep->v.p[1]->v.p[0]->v.i);
  614.                 return;
  615.             }
  616.         }
  617.         ref2_double(ep);
  618.         if (ep->v.p[0]->nodetype == en_fcon && ep->v.p[1]->nodetype == en_fcon)
  619.             dooper(node);
  620.         break;
  621.     case en_fmuld:
  622.         opt0(&(ep->v.p[0]));
  623.         opt0(&(ep->v.p[1]));
  624.         if (fetchdouble(ep->v.p[0], &dval)) {
  625.             if (dval == 0.0) {  /* 0.0 * X */
  626.                 *node = ep->v.p[0];
  627.                 return;
  628.             }
  629.             if (dval == 1.0) {  /* 1.0 * X */
  630.                 *node = ep->v.p[1];
  631.                 (void) remlit(ep->v.p[0]->v.p[0]->v.i);
  632.                 return;
  633.             }
  634.         }
  635.         if (fetchdouble(ep->v.p[1], &dval)) {
  636.             if (dval == 0.0) {  /* X * 0.0 */
  637.                 *node = ep->v.p[1];
  638.                 return;
  639.             }
  640.             if (dval == 1.0) {  /* X * 1.0 */
  641.                 *node = ep->v.p[0];
  642.                 (void) remlit(ep->v.p[1]->v.p[0]->v.i);
  643.                 return;
  644.             }
  645.         }
  646.         ref2_double(ep);
  647.         if (ep->v.p[0]->nodetype == en_fcon && ep->v.p[1]->nodetype == en_fcon)
  648.             dooper(node);
  649.         break;
  650.     case en_fdivd:
  651.         opt0(&(ep->v.p[0]));
  652.         opt0(&(ep->v.p[1]));
  653.         if (fetchdouble(ep->v.p[0], &dval)) {
  654.             if (dval == 0.0) {  /* 0.0 / X */
  655.                 *node = ep->v.p[0];
  656.                 return;
  657.             }
  658.         }
  659.         if (fetchdouble(ep->v.p[1], &dval)) {
  660.             if (dval == 1.0) {  /* X / 1.0 */
  661.                 *node = ep->v.p[0];
  662.                 (void) remlit(ep->v.p[1]->v.p[0]->v.i);
  663.                 return;
  664.             }
  665.         }
  666.         ref2_double(ep);
  667.         if (ep->v.p[0]->nodetype == en_fcon && ep->v.p[1]->nodetype == en_fcon)
  668.             dooper(node);
  669.         break;
  670.     case en_fmodd:
  671.     case en_fadds:
  672.     case en_fsubs:
  673.     case en_fmuls:
  674.     case en_fdivs:
  675.     case en_fmods:
  676.         opt0(&(ep->v.p[0]));
  677.         opt0(&(ep->v.p[1]));
  678.         ref2_double(ep);
  679.         if (ep->v.p[0]->nodetype == en_fcon && ep->v.p[1]->nodetype == en_fcon)
  680.             dooper(node);
  681.         break;
  682.     case en_cld:
  683.     case en_clf:
  684.         opt0(&(ep->v.p[0]));
  685.         if (ep->v.p[0]->nodetype == en_icon)
  686.             dooper(node);
  687.         break;
  688.     case en_cdl:
  689.     case en_cfl:
  690.         opt0(&(ep->v.p[0]));
  691.         ref_double(ep);
  692.         if (ep->v.p[0]->nodetype == en_fcon)
  693.             dooper(node);
  694.         break;
  695.     default:
  696.         break;
  697.     }
  698. }
  699.  
  700. long
  701. xfold(node)
  702.  
  703. /*
  704.  * xfold will remove constant nodes and return the values to the calling
  705.  * routines.
  706.  */
  707.     struct enode   *node;
  708. {
  709.     long            i;
  710.  
  711.     if (node == NULL)
  712.         return 0;
  713.     switch (node->nodetype) {
  714.     case en_icon:
  715.         i = node->v.i;
  716.         node->v.i = 0;
  717.         return i;
  718.     case en_add:
  719.         return xfold(node->v.p[0]) + xfold(node->v.p[1]);
  720.     case en_sub:
  721.         return xfold(node->v.p[0]) - xfold(node->v.p[1]);
  722.     case en_mul:
  723.         if (node->v.p[0]->nodetype == en_icon)
  724.             return xfold(node->v.p[1]) * node->v.p[0]->v.i;
  725.         else if (node->v.p[1]->nodetype == en_icon)
  726.             return xfold(node->v.p[0]) * node->v.p[1]->v.i;
  727.         else
  728.             return 0;
  729.     case en_uminus:
  730.         return -xfold(node->v.p[0]);
  731.     case en_lsh:
  732.     case en_rsh:
  733.     case en_div:
  734.     case en_mod:
  735.     case en_umod:
  736.     case en_asadd:
  737.     case en_assub:
  738.     case en_asmul:
  739.     case en_asdiv:
  740.     case en_asmod:
  741.     case en_asumul:
  742.     case en_asudiv:
  743.     case en_asumod:
  744.     case en_and:
  745.     case en_land:
  746.     case en_or:
  747.     case en_lor:
  748.     case en_xor:
  749.     case en_asand:
  750.     case en_asor:
  751.     case en_void:
  752.     case en_fcall:
  753.     case en_assign:
  754.         fold_const(&node->v.p[0]);
  755.         fold_const(&node->v.p[1]);
  756.         return 0;
  757.     case en_faddd:
  758.     case en_fsubd:
  759.     case en_fmuld:
  760.     case en_fdivd:
  761.     case en_fmodd:
  762.     case en_fadds:
  763.     case en_fsubs:
  764.     case en_fmuls:
  765.     case en_fdivs:
  766.     case en_fmods:
  767.         fold_const(&node->v.p[0]);
  768.         fold_const(&node->v.p[1]);
  769.         return 0;
  770.     case en_fnegd:
  771.     case en_fnegs:
  772.     case en_d_ref:
  773.     case en_f_ref:
  774.         fold_const(&node->v.p[0]);
  775.         return 0;
  776.     case en_b_ref:
  777.     case en_ub_ref:
  778.     case en_w_ref:
  779.     case en_uw_ref:
  780.     case en_l_ref:
  781.     case en_m_ref:
  782.     case en_compl:
  783.     case en_not:
  784.         fold_const(&node->v.p[0]);
  785.         return 0;
  786.     }
  787.     return 0;
  788. }
  789.  
  790. void
  791. fold_const(node)
  792.  
  793. /*
  794.  * reorganize an expression for optimal constant grouping.
  795.  */
  796.     struct enode  **node;
  797. {
  798.     struct enode   *ep;
  799.     long            i;
  800.  
  801.     ep = *node;
  802.     if (ep == NULL)
  803.         return;
  804.     if (ep->nodetype == en_add) {
  805.         if (ep->v.p[0]->nodetype == en_icon) {
  806.             ep->v.p[0]->v.i += xfold(ep->v.p[1]);
  807.             return;
  808.         }
  809.         else if (ep->v.p[1]->nodetype == en_icon) {
  810.             ep->v.p[1]->v.i += xfold(ep->v.p[0]);
  811.             return;
  812.         }
  813.     }
  814.     else if (ep->nodetype == en_sub) {
  815.         if (ep->v.p[0]->nodetype == en_icon) {
  816.             ep->v.p[0]->v.i -= xfold(ep->v.p[1]);
  817.             return;
  818.         }
  819.         else if (ep->v.p[1]->nodetype == en_icon) {
  820.             ep->v.p[1]->v.i -= xfold(ep->v.p[0]);
  821.             return;
  822.         }
  823.     }
  824.     i = xfold(ep);
  825.     if (i != 0) {
  826.         ep = makenode(en_icon, i, NULL);
  827.         ep = makenode(en_add, ep, *node);
  828.         *node = ep;
  829.     }
  830. }
  831.  
  832. void
  833. opt4(node)
  834.  
  835. /*
  836.  * apply all constant optimizations.
  837.  */
  838.     struct enode  **node;
  839. {
  840.     opt0(node);
  841.     fold_const(node);
  842.     opt0(node);
  843. }
  844.